﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using Microsoft.SharePoint;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.Administration.Claims;
using Microsoft.SharePoint.Meetings;
using Microsoft.SharePoint.Utilities;
using TemplateLibraryConnector.Data;
using TemplateLibraryConnector.Utility;
using TemplateLibraryConnector.ServerControls;


namespace TemplateLibraryConnector.UI
{
    internal class TemplateHubController
    {
        internal readonly TemplateLibrarySettings _settings;
        private static string _templateHubAddress; 
        private static string _templateLibrary;

        public TemplateHubController(string destonationUrl)
        {
            using (var destinationSite = TemplateLibraryDataUtility.GetDocumentLibrarySite(destonationUrl))
            {
                using (var destinationWeb = TemplateLibraryDataUtility.GetDocumentLibraryWeb(destonationUrl, destinationSite))
                {
                    var list = destinationWeb.GetList(destonationUrl) as SPDocumentLibrary;

                    _settings = TemplateLibrarySettings.LoadFromList(list);
                    _templateHubAddress = _settings.GetTemplateHubAddress(string.Empty);
                }
            }

            //get the document library name - must be a better way?
            var templateHubUrl = _settings.GetTemplateHubAddress(string.Empty);
            if (_settings.TemplateListIds != string.Empty)
            {
                var listId = new Guid(_settings.TemplateListIds);
                using (var templateHubSite = TemplateLibraryDataUtility.GetDocumentLibrarySite(templateHubUrl))
                {
                    using (var templateHubWeb = TemplateLibraryDataUtility.GetDocumentLibraryWebFromUrl(templateHubUrl, templateHubSite))
                    {
                        _templateLibrary = templateHubWeb.Lists[listId].RootFolder.Url;
                    }
                }
            }
            
        }

        
        public void PopulateDataSource(TemplateViewType type, Object datagrid, string strSearch, Guid selectedViewId, PagedDataSource pagedDataSource)
        {
            
            if (datagrid is SPGridViewMultiSortFilter)
            {
                var gridView = (SPGridViewMultiSortFilter)datagrid;
                GenerateColumns(type, selectedViewId, gridView);
                
                var gridDS = gridView.SetObjectDataSource("GridView", type, strSearch, _settings, selectedViewId);

                //remove the old control first since we do a reload
                var oldDataSource = gridView.NamingContainer.FindControl("GridView");
                if (oldDataSource != null)
                {
                    gridView.NamingContainer.Controls.Remove(oldDataSource);
                }

                gridView.NamingContainer.Controls.Add(gridDS);

            }
            else if (datagrid is DataList)
            {
                var items = TemplateLibraryFactory.GetTemplates(type, _settings).GetItems(selectedViewId);
                var dt = TemplateLibraryDataUtility.PerformFilter(items, strSearch);
                var dataList = (DataList)datagrid;

                dataList.ItemTemplate = new ThumbNailTemplate(); 
                
                pagedDataSource.DataSource = dt.DefaultView;
                
                dataList.DataSource = pagedDataSource;
            }
      
        }

        public static Uri DoILikeThis(string fileName)
        {
            var fileNameUrl = new Uri(_templateHubAddress + fileName);
            const string deleteFav = "_layouts/15/TemplateLibraryConnector/Images/deleteFav.png";
            const string addFav = "_layouts/15/Images/ADDTOFAVORITES.GIF";

            var favButtonImageUrl = FavoriteTemplates.DoILikeThis(fileNameUrl) ? new Uri(_templateHubAddress+deleteFav) : new Uri(_templateHubAddress+addFav);

            return favButtonImageUrl;
        }

        public static string GetThumbNail(string thumbNailPrefix, string fileName)
        {
            var thumbNailUrl = thumbNailPrefix + "FilePath=" + _templateHubAddress + _templateLibrary + @"/" + fileName;
            return thumbNailUrl;
        }

        //based on the view, create the columns and headers
        internal void GenerateColumns(TemplateViewType type, Guid selectedViewId, SPGridViewMultiSortFilter detailGrid)
        {
            detailGrid.Columns.Clear();

            var templatesFields = TemplateLibraryDataUtility.TemplateFields(_settings, selectedViewId, false);

            detailGrid.MultiValuesFields = "";
            detailGrid.FilterDataFields = ",";

            foreach (var field in templatesFields)
            {
                var gridField = new BoundField
                                    {
                                        HeaderText = field.Title,
                                        DataField = field.InternalName,
                                        SortExpression = field.InternalName
                                    };


                detailGrid.Columns.Add(gridField);

                detailGrid.FilterDataFields += gridField.SortExpression + ", ";
                if (field.InternalName == "TaxKeyword")
                    detailGrid.MultiValuesFields += field.InternalName;
            }

            //We have problems with the last column header because we have an extra column in the headers to the data; Add a dummy column
            detailGrid.Columns.Add(new TemplateField {HeaderText = "", SortExpression = "" });

        }

        public static Dictionary<string,string> GetMetaData(SPListItem viewItem)
        {
            var metaData = new Dictionary<string,string>();
            
            if (viewItem!=null)
            {
                //Get a reference to the item again by the ID because from the view it is often not filled
                var item = viewItem.ParentList.GetItemById(viewItem.ID);

                var fields = item.Fields;

                var config = XDocument.Load(SPUtility.GetVersionedGenericSetupPath("config", 15) + @"\MetaData.xml");

                foreach (
                        var field in 
                        from f in config.Descendants(@"MetaDataColumn") select f.Element("DisplayName") into dispText 
                        where dispText != null select dispText.Value into fieldName 
                        where item.Fields.ContainsField(fieldName) select item.Fields[fieldName] into field 
                        where field != null select field)
                {
                    metaData.Add(field.StaticName, field + "|" + (item[field.Id] != null ? field.GetFieldValueAsText(item[field.Id]) : ""));
                }
            }

            return metaData;
        }


        public static bool AddOrRemoveFavorite(string fileUrl, string fileTitle)
        {
            var templateUrl = new Uri(_templateHubAddress + fileUrl);
            
            if (!FavoriteTemplates.DoILikeThis(templateUrl))
            {
                FavoriteTemplates.Like(templateUrl, fileTitle);
                return true;
            }
            FavoriteTemplates.UnLike(templateUrl);
            return false;
            
        }

        public static void UpdateLastUsedProperty(string fileName, string currentUser, Guid siteCollection)
        {
            
            LastUsedTemplates.UpdateLastUsedProperty(fileName, currentUser, siteCollection);
            
        }

        public static string CreateTemplate(string fileVersionUrl, string destinationLibraryUrl)
        {

            var urldec = SPHttpUtility.HtmlDecode(fileVersionUrl);
            var destLibrary = SPHttpUtility.EcmaScriptStringLiteralEncode(destinationLibraryUrl);
            var thisWeb = SPContext.Current.Web;
            var encodedFileUrl = SPHttpUtility.EcmaScriptStringLiteralEncode(urldec);

            // checks if the site we are running this fuctionality on is a meeting site. 
            if (SPMeeting.IsMeetingWorkspaceWeb(thisWeb))
            {
                var meeting = SPMeeting.GetMeetingInformation(SPContext.Current.Web);
                destLibrary = destinationLibraryUrl + "/" + meeting.InstanceId.ToString(CultureInfo.InvariantCulture); ;
            }
            else
            {
                destLibrary = destinationLibraryUrl;
            }

            var createNewTemplate = string.Format(@"javascript:createNewDocumentWithProgID('{0}', '{1}', 'SharePoint.OpenDocuments', false); SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, 'Selected'); ",
                  encodedFileUrl, destLibrary);
        
            return createNewTemplate;
        }

        public static string RemoveClaimsStuffFromLoginName(string loginName)
        {
            var mgr = SPClaimProviderManager.Local;
            if (mgr != null)
            {
                SPClaim claim = null;
                try
                {
                    claim = mgr.DecodeClaim(loginName);
                }
                catch (ArgumentException)
                {
                    //System account gived ArgumentException
                }

                if (claim != null)
                    loginName = mgr.DecodeClaim(loginName).Value;
            }
            return loginName;
        }

        public static string GetFileVersion(string fileName)
        {
            var fileUrl = _templateHubAddress + _templateLibrary + "/" + fileName;
            var fileversionurl = fileUrl;

            using (var site = new SPSite(_templateHubAddress))
            {
                using (var web = site.OpenWeb(_templateHubAddress))
                {
                    var file = !fileUrl.Contains("http://") ? web.GetListItem(web.Url + "/" + fileUrl) : web.GetListItem(fileUrl);
                    if (file.HasPublishedVersion)
                    {
                        var publishedVersion = file.Versions.Cast<SPListItemVersion>().First(fv => fv.Level == SPFileLevel.Published && fv.IsCurrentVersion);
                        var currentVersion = file.Versions.Cast<SPListItemVersion>().First(fv => fv.IsCurrentVersion);

                        // Generate history url if there are minor versions present (NOTE: using _vti_history for current version does NOT work!)
                        if (web.DoesUserHavePermissions(web.CurrentUser.LoginName, SPBasePermissions.EditListItems) && (publishedVersion.VersionId != currentVersion.VersionId))
                            fileversionurl = _templateHubAddress + "_vti_history/" + publishedVersion.VersionId + "/" + publishedVersion.Url;
                        else
                            fileversionurl = _templateHubAddress + publishedVersion.Url;
                    }
                }
            }
            return fileversionurl;
        }
    }

}
